BonusFrame = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0", "FuBarPlugin-2.0", "AceHook-2.1", "AceDebug-2.0")
local g = AceLibrary("Gratuity-2.0")
local dewdrop = AceLibrary("Dewdrop-2.0")
local tablet = AceLibrary("Tablet-2.0")
local bonus = AceLibrary("ItemBonusLib-1.0")

BonusFrame:RegisterDB("BonusFrameSV", "BonusFrameSVPC")
BonusFrame:RegisterDefaults("profile", {
   ["IgnoreStats"] = true
} )
local Cbonuses = {}
local comparelink = ""

function BonusFrame:OnInitialize()
	self.INV_SLOT = {
		["INVTYPE_AMMO"]={0},
		["INVTYPE_HEAD"]={1},
		["INVTYPE_NECK"]={2},
		["INVTYPE_SHOULDER"]={3},
		["INVTYPE_BODY"]={4},
		["INVTYPE_CHEST"]={5},
		["INVTYPE_ROBE"]={5},
		["INVTYPE_WAIST"]={6},
		["INVTYPE_LEGS"]={7},
		["INVTYPE_FEET"]={8},
		["INVTYPE_WRIST"]={9},
		["INVTYPE_HAND"]={10},
		["INVTYPE_FINGER"]={11,12},
		["INVTYPE_TRINKET"]={13,14},
		["INVTYPE_CLOAK"]={15},
		["INVTYPE_WEAPON"]={16,17},
		["INVTYPE_SHIELD"]={17},
		["INVTYPE_2HWEAPON"]={16,17},
		["INVTYPE_WEAPONMAINHAND"]={16},
		["INVTYPE_WEAPONOFFHAND"]={17},
		["INVTYPE_HOLDABLE"]={17},
		["INVTYPE_RANGED"]={18},
		["INVTYPE_THROWN"]={18},
		["INVTYPE_RANGEDRIGHT"]={18},
		["INVTYPE_RELIC"]={18},
		["INVTYPE_TABARD"]={19},
	}
	
	self.TooltipList = {
		ShoppingTooltip1,
		ShoppingTooltip2,
		--EQCompare support
		EQCompareTooltip1,
		EQCompareTooltip2,
		--tekKompare support
		tekKompareTooltip1,
		tekKompareTooltip2,
	}

	self.MethodList = {
		["SetHyperlink"] = "a",
		["SetBagItem"] = "GetContainerItemLink(a, b)",
		["SetInventoryItem"] = "GetInventoryItemLink(a, b)",
		-- auction
		["SetAuctionItem"] = "GetAuctionItemLink(a, b)",
		-- loot
		["SetLootItem"] = "GetLootSlotLink(a, b)",
		["SetLootRollItem"] = "GetLootRollItemLink(a, b)",
		-- crafting
		["SetCraftSpell"] = "GetCraftItemLink(a)",
		["SetCraftItem"] = "GetCraftReagentItemLink(a, b)",
		["SetTradeSkillItem"] = "nil;if b then link=GetTradeSkillReagentItemLink(a, b) else link=GetTradeSkillItemLink(a) end",
		-- buffs
		["SetPlayerBuff"] = "nil",
		-- quest log
		["SetQuestItem"] = "GetQuestItemLink(a, b)",
		["SetQuestLogItem"] = "GetQuestLogItemLink(a, b)",
		-- trade
		["SetTradePlayerItem"] = "GetTradePlayerItemLink(a)",
		["SetTradeTargetItem"] = "GetTradeTargetItemLink(a)",
		-- vendor tooltip
		["SetMerchantItem"] = "GetMerchantItemLink(a)",
	}
	
	self.ClassIgnoreList = {
		-------------------------------------------------------
		-- List of which stats to ignore for each class		 --
		-- If a class is listed under a stat, it			 --
		-- means that its an unnecessary stat for that class --
		-------------------------------------------------------
		--Base Stats
		["AGI"] = {"MAGE","PALADIN","PRIEST","WARLOCK",},
		["INT"] = {"ROGUE","WARRIOR",},
		["SPI"] = {"ROGUE","WARRIOR",},
		--["STA"] = {},
		["STR"] = {"MAGE","PRIEST",},
		--Resistances
		--["ARCANERES"] = {},
		--["FIRERES"] = {},
		--["FROSTRES"] = {},	--Everyone cares about resistances!
		--["NATURERES"] = {},
		--["SHADOWRES"] = {},
		--skills
		--["FISHING"] = {},
		--["MINING"] = {},
		--["HERBALISM"] = {},  --Skills too!
		--["SKINNING"] = {},
		--["DEFENSE"] = {},
		--Melee
		["BLOCK"] = {"DRUID","HUNTER","MAGE","ROGUE","WARLOCK",},
		["BLOCKVALUE"] = {"DRUID","HUNTER","MAGE","ROGUE","WARLOCK",},
		["DODGE"] = {"MAGE","PRIEST","WARLOCK",},
		["ATTACKPOWER"] = {"MAGE","PRIEST","WARLOCK",},
		["ATTACKPOWERUNDEAD"] = {"MAGE","PRIEST","WARLOCK",},
		["ATTACKPOWERBEAST"] = {"MAGE","PRIEST","WARLOCK",},
		["ATTACKPOWERDEMON"] = {"MAGE","PRIEST","WARLOCK",}, 
		["ATTACKPOWERFERAL"] = {"ROGUE","HUNTER","MAGE","PALADIN","PRIEST","SHAMAN","WARLOCK","WARRIOR",},
		["CRIT"] = {"MAGE","PRIEST","WARLOCK",},
		["TOHIT"] = {"MAGE","PRIEST","WARLOCK",},
		--Ranged
		["RANGEDATTACKPOWER"] = {"DRUID","ROGUE","MAGE","PALADIN","PRIEST","SHAMAN","WARLOCK","WARRIOR",},
		["RANGEDCRIT"] = {"DRUID","ROGUE","MAGE","PALADIN","PRIEST","SHAMAN","WARLOCK","WARRIOR",},
		--Spells
		["DMG"] = {"HUNTER","ROGUE","WARRIOR",},
		["HEAL"] = {"HUNTER","MAGE","ROGUE","WARRIOR",},
		["DMGUNDEAD"] = {"HUNTER","ROGUE","WARRIOR",},
		["ARCANEDMG"] = {"HUNTER","PALADIN","PRIEST","ROGUE","SHAMAN","WARLOCK","WARRIOR",},
		["FIREDMG"] = {"DRUID","HUNTER","PALADIN","PRIEST","ROGUE","WARRIOR",},
		["FROSTDMG"] = {"DRUID","HUNTER","PALADIN","PRIEST","ROGUE","WARLOCK","WARRIOR",},
		["HOLYDMG"] = {"DRUID","HUNTER","MAGE","ROGUE","SHAMAN","WARLOCK","WARRIOR",},
		["NATUREDMG"] = {"HUNTER","MAGE","PALADIN","PRIEST","ROGUE","WARLOCK","WARRIOR",},
		["SHADOWDMG"] = {"DRUID","HUNTER","MAGE","PALADIN","ROGUE","SHAMAN","WARRIOR",},
		["SPELLCRIT"] = {"HUNTER","ROGUE","WARRIOR",},
		["HOLYCRIT"] = {"DRUID","HUNTER","MAGE","ROGUE","SHAMAN","WARLOCK","WARRIOR",},
		["SPELLTOHIT"] = {"HUNTER","ROGUE","WARRIOR",},
		["SPELLPEN"] = {"HUNTER","ROGUE","WARRIOR",},
		--Regen
		--["HEALTHREG"] = {},
		["MANAREG"] = {"ROGUE","WARRIOR",},
		--["HEALTH"] = {},
		["MANA"] = {"ROGUE","WARRIOR",},
		--Combat Ratings
		["CR_WEAPON"] = {"DRUID","HUNTER","MAGE","PRIEST","WARLOCK",},
		["CR_WEAPON_AXE"] = {"DRUID","HUNTER","MAGE","PRIEST","ROGUE","WARLOCK",},
		["CR_WEAPON_DAGGER"] = {"DRUID","HUNTER","MAGE","PRIEST","WARLOCK",},
		["CR_WEAPON_MACE"] = {"DRUID","HUNTER","MAGE","PRIEST","WARLOCK",},
		["CR_WEAPON_SWORD"] = {"DRUID","HUNTER","MAGE","PRIEST","SHAMAN","WARLOCK",}, 
		["CR_WEAPON_SWORD_2H"] = {"DRUID","HUNTER","MAGE","PRIEST","ROGUE","SHAMAN","WARLOCK",},
		["CR_DEFENSE"] = {"HUNTER","MAGE","PRIEST","ROGUE","SHAMAN","WARLOCK",},
		["CR_DODGE"] = {"MAGE","PRIEST","WARLOCK",},
		["CR_PARRY"] = {"DRUID","MAGE","PRIEST","WARLOCK",},
		["CR_BLOCK"] = {"DRUID","ROGUE","HUNTER","MAGE","PRIEST","WARLOCK",},
		["CR_HIT"] = {"MAGE","PRIEST","WARLOCK",},
		["CR_CRIT"] = {"MAGE","PRIEST","WARLOCK",},
		["CR_HASTE"] = {"MAGE","PRIEST","WARLOCK",},
		["CR_SPELLHIT"] = {"HUNTER","ROGUE","WARRIOR",},
		["CR_SPELLCRIT"] = {"HUNTER","ROGUE","WARRIOR",},
		["CR_SPELLHASTE"] = {"HUNTER","ROGUE","WARRIOR",},
		--["CR_RESILIENCE"] = {},
	}
	
	self.anchor = {
		[1] = "GameTooltip",
		[2] = "GameTooltip"
	}
	
	self:SetupFrame()
	--self:SetDebugging(true)
	self.OnMenuRequest = {
		type="group",
		args = {
			item = {
				name = "Ignore Stats", type = 'toggle',
				desc = "Remove useless stats from the frame",
				get = 	function()
							return self.db.profile.IgnoreStats
						end,
				set = 	function(v)
							self.db.profile.IgnoreStats = v
						end,
			},
		},
	}
	self:RegisterChatCommand(
		{ "/bonusframe", "/bonusf", "/bf" })
end

function BonusFrame:SetupFrame()
	self.frame1 = CreateFrame("GameTooltip", "BonusFrame1", GameTooltip, "GameTooltipTemplate")
	self.frame2 = CreateFrame("GameTooltip", "BonusFrame2", GameTooltip, "GameTooltipTemplate")

	
	for i=1, 2 do
		local name = getglobal("BonusFrame" .. i)
		name:SetPoint("CENTER",0,0)
	end
end

function BonusFrame:OnEnable()

	--[[for _,v in pairs(self.TooltipList) do
		self:HookScript(v, "OnShow", "EQ_OnShow")
		self:HookScript(v, "OnHide", "EQ_OnHide")
	end]]--
	
	--[[for methodName, getLink in pairs(self.MethodList) do
		handlerString = "function BonusFrame:"..methodName.."(tooltip, a, b) local link = "..getLink.." self:PreCompare(link) end"
		loadstring(handlerString)()
	end
	
	for methodName, _ in pairs(self.MethodList) do
		self:SecureHook(GameTooltip, methodName)
	end]]--
	self:HookScript(GameTooltip, "OnTooltipSetItem")
	self:SecureHook("SetItemRef")

end

function BonusFrame:OnTooltipSetItem(frame, ...)
	self:Debug("OnTooltipSetItem")
	local f = GetMouseFocus() and GetMouseFocus():GetName() or ""
	if f == "WorldFrame" or string.find(f, "^Character.*Slot$") or string.find(f, "^TempEnchant%d+$") then return end
	local _, link = frame:GetItem()
	self:GetAnchor(false)
	self:Compare(link, 0)
	return self.hooks[GameTooltip].OnTooltipSetItem(frame, ...)
end

function BonusFrame:SetItemRef(link, text, button)
	if strfind(link,"^item") then
		self:GetAnchor(true)
		self:Compare(link, 2)
	end
end

function BonusFrame:EQ_OnShow(object)
	self:Debug("OnShow", object:GetName())
	local num = string.sub((object:GetName()), -1) 
	local f = getglobal("BonusFrame"..num)
	f:ClearAllPoints()
	f:Show()	
	self.hooks[object]["OnShow"]()
end

function BonusFrame:EQ_OnHide(object)
	self.frame1:Hide()	
	self.frame2:Hide()
	self.hooks[object]["OnHide"]()
end

function BonusFrame:GetAnchor(sir)
	self.anchor = "GameTooltip"
	if sir then		--From SetItemRef
		if EQCompare then
			self.anchor = {
				[1] = "ShoppingTooltip1",
				[2] = "ShoppingTooltip2"
			}
		elseif tekKompareTooltip3 then
			self.anchor = {
				[1] = "tekKompareTooltip3",
				[2] = "tekKompareTooltip4"
			}
		end
	else			--From Mouseover
		if EQCompare then
			self.anchor = {
				[1] = "EQCompareTooltip1",
				[2] = "EQCompareTooltip2"
			}
		elseif tekKompareTooltip1 then
			self.anchor = {
				[1] = "tekKompareTooltip1",
				[2] = "tekKompareTooltip2"
			}
		end
	end
end

--Comparison Functions
function BonusFrame:PreCompare(itemLink)
	if (itemLink == nil) then return end
	local _,_, link = string.find(itemLink, "^|%x+|H(.+)|h%[.+%]")
	self:Compare(link)
end

function BonusFrame:Compare(link, offset)
	self:Debug("Compare")
	
	local _,ilink,_,_,_,_,_,_,loc = GetItemInfo(link)
	local EQlink
	local framenum = 1
	
	for _, v in ipairs(self.INV_SLOT[loc] or {}) do
		local sf = getglobal("BonusFrame" .. framenum)
		local sf1 = getglobal("BonusFrame" .. framenum .. "TextLeft1")
		
		local anchor = self.anchor[framenum]
		--local sfd = getglobal("BonusFrame" .. framenum .. "Data")
		--local sfn = getglobal("BonusFrame" .. framenum .. "Nums")
		sf:SetOwner(GameTooltip, "ANCHOR_NONE")
		sf:ClearAllPoints()
		sf:SetPoint("TOP", anchor, "BOTTOM", 0, 0)
		sf:AddLine("Bonuses")
		sf1:SetFont(sf1:GetFont(), 11)
		EQlink = GetInventoryItemLink("player",v)
		if (EQlink == nil) then return end
		
		self:Debug("Link: " .. ilink)
		self:Debug("Equipped: " .. EQlink)
		local bonuses = bonus:ScanItem(ilink, true)
		local EQbonuses = {}
		EQbonuses = bonus:ScanItem(EQlink, true)
		Cbonuses = {}
		for k, v in pairs(EQbonuses) do
			self:Debug("Equipped stat: " .. k)
			if(bonuses[k]) then		--got matching stats, compare em
				self:Debug("match")
				Cbonuses[k] = bonuses[k] - v
				self:Debug(bonuses[k] .. "(I) - " .. v .. "(E) = " .. Cbonuses[k])
			else					--equipped has a stat the other doesnt, leave it alone
				self:Debug("no match")
				Cbonuses[k] = -v
				self:Debug("0(I) - " .. v .. "(E) = " .. Cbonuses[k])
			end
		end
		self:Debug("Done first loop")
		for k, v in pairs(bonuses) do
			if (EQbonuses[k] == nil) then
				self:Debug("Adding Item stat: " .. k)
				Cbonuses[k] = v
				self:Debug(v .. "(I) - 0(E) = " .. Cbonuses[k])
			end
		end
		-------------------------
		--sfd:SetText("")
		--sfn:SetText("")
		local showme = false
		for k, v in self:Sorted(Cbonuses, function(a,b) return bonus:ConvertRating(a,Cbonuses[a])>bonus:ConvertRating(b,Cbonuses[b]) end) do
			self:Debug(k .. ": " .. v)
			if not(v == 0) and not(self:ClassIgnore(k)) then
				if(string.find(k, "CR_")) then
					if(v > -1) then 
						v = "|cFF00FF00+" .. v .. "(" .. bonus:ConvertRating(k, v) .. "%)|r"
					else
						v = "|cFFFF0000" .. v .. "(" .. bonus:ConvertRating(k, v) .. "%)|r"
					end
				else
					if(v > -1) then 
						v = "|cFF00FF00+" .. v .. "|r"
					else
						v = "|cFFFF0000" .. v .. "|r"
					end
				end
				sf:AddDoubleLine(bonus:GetBonusFriendlyName(k), v, 1,1,1)
				--sfd:SetText((sfd:GetText() or "") ..  bonus:GetBonusFriendlyName(k) .. ": |n")
				--sfn:SetText((sfn:GetText() or "") .. v .. "|n")			
				showme = true
			end
		end
		-------------------------
		--[[size = size*14
		sf:SetHeight(size + 25)
		self:Debug("Height set to ", size + 25)
		local width = sfd:GetWidth() + sfn:GetWidth() + 12
		if (width < 70) then width = 70 end
		sf:SetWidth(width)
		self:Debug("Width Set to ", width)]]--
		framenum = framenum + 1
		if showme == true then
			self:Debug("Showing")
			sf:Show() 
		end
	end
end

function BonusFrame:Sorted(t, f)
	local a = {}
	for n in pairs(t) do table.insert(a, n) end
	table.sort(a, f)
	local i = 0      -- iterator variable
	local iter = function ()   -- iterator function
		i = i + 1
		if a[i] == nil then return nil
		else return a[i], t[a[i]]
		end
	end
	return iter
end

function BonusFrame:ClassIgnore(stat)
	--  True: Ignore the stat
	-- False: Add the stat in
	if (self.db.profile.IgnoreStats == true) then
		local _,class = UnitClass("player")
		if not(self.ClassIgnoreList[stat]) then return false end	--False: stat not found in table
		for _,v in pairs(self.ClassIgnoreList[stat]) do
			if(v == class) then return true end			--True: stat was found for the players class
		end	
	end
	return false										--False: option is off, not ignoring any stats
end

function BonusFrame:Bug(num)
	self:Print(self.anchor[1], self.anchor[2])
end

function BonusFrame:OnTooltipUpdate()
	local cat = tablet:AddCategory(
		'columns', 2
	)
	for k, v in self:Sorted(Cbonuses, function(a,b) return bonus:ConvertRating(a,Cbonuses[a])>bonus:ConvertRating(b,Cbonuses[b]) end) do
		self:Debug(k .. ": " .. v)
		if not(v == 0) and not(self:ClassIgnore(k)) then
			if(string.find(k, "CR_")) then
				if(v > -1) then 
					v = "|cFF00FF00+" .. v .. "(" .. bonus:ConvertRating(k, v) .. "%)|r"
				else
					v = "|cFFFF0000" .. v .. "(" .. bonus:ConvertRating(k, v) .. "%)|r"
				end
			else
				if(v > -1) then 
					v = "|cFF00FF00+" .. v .. "|r"
				else
					v = "|cFFFF0000" .. v .. "|r"
				end
			end
			cat:AddLine(
				'text', bonus:GetBonusFriendlyName(k),
				'text2', v
			)
		end
	end
end
